﻿# -*- coding: utf-8 -*-
import gluon.utils as utils
from gluon.tools import Mail, Auth, Crud
import string
from random import choice

class ProfessorsAuth(Auth):
	def __init__(self,*args):
		Auth.__init__(self, *args)
		self.settings.login_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/zaloguj')
		self.settings.logout_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/wyloguj')
		self.settings.register_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/rejestruj')
		self.settings.profile_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/profil')
		self.settings.profile_next = URL(a='instytut',c='uzytkownicy',f='uzytkownik/profil')
		self.settings.change_password_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/zmien_haslo')
		self.settings.retrieve_password_url = URL(a='instytut',c='uzytkownicy',f='uzytkownik/odzyskaj_haslo')
		self.settings.register_next = None
		self.settings.login_next = URL(a='instytut',c='home',f='index')
		
		self.settings.on_failed_authorization=URL(a='instytut',c='home',f='komunikat', vars={'message': "Nie posiadasz uprawnien"})
		
		self.settings.submit_button='Zatwierdź'
		
		self.messages.new_password = 'Nowe haslo' 
		self.messages.old_password = 'Stare haslo'
		self.messages.mismatched_password = 'Hasła się nie zgadzają"' 
		#self.messages.submit_button = 'Wyślij'
		
		self.messages.retrieve_password_subject=u'Hasło do systemu wfa'.encode('iso-8859-2')
		self.messages.retrieve_password=u'Twoje hasło to %(password)s'.encode('iso-8859-2')
		
		mail=Mail()
		#mail.settings.server = 'ift.uni.wroc.pl:25' #trzeba wziąść skąd te dane
		#mail.settings.sender = 'apracnauk@ift.uni.wroc.pl'
		#mail.settings.login = 'apracnauk:LohzaeOa'
		#mail.settings.server = 'poczta.o2.pl:25' #trzeba wziąść skąd te dane
		#mail.settings.sender = 'baboss@o2.pl'
		#mail.settings.login = 'baboss:blitzart'
		mail.settings.server = 'poczta.o2.pl:25' #trzeba wziąść skąd te dane
		mail.settings.sender = 'apracnauk@o2.pl'
		mail.settings.login = 'apracnauk:Shahy1ei'
		self.settings.mailer=mail

		self.settings.profile_onaccept=self.odswierz
		
		self.settings.table_group_name='rola'
		self.settings.table_group=db.rola
		self.settings.table_user_name = 'uzytkownicy' 
		self.settings.table_user = db.uzytkownicy
		
		self.grupa_administrator=1
		self.grupa_moderator_instytutowy=2
		self.grupa_pracownik=3
	
	def random_password(self,length=8, chars=string.letters + string.digits):
		return ''.join([choice(chars) for i in range(length)])
	
	def retrieve_password(
		self, 
		next=DEFAULT, 
		onvalidation=DEFAULT, 
		onaccept=DEFAULT, 
		log=DEFAULT, 
		): 
		if onvalidation == DEFAULT: 
			onvalidation = self.settings.retrieve_password_onvalidation 

		form = FORM(TABLE(TR("Email: ", INPUT(_type='text', _name="email", 
		     requires=[IS_EMAIL(), IS_IN_DB(db, 'pracownicy.email', error_message="podany email nie istnieje")])),
						TR("", INPUT(_type='submit', _value='Wyślij')),
				))
		if form.accepts(request.vars,session,formname='retrieve_password', onvalidation=onvalidation): 
			#znajdz pracownika i wez jego id, na pewno jest - validacja przez request w formularzu
			pracownik = db(db.pracownicy.email==request.vars.email).select(db.pracownicy.id)[0]
			#znajdz uzytkownika wskazującego na takiego użytkownika
			user = db(db.uzytkownicy.id_pracownik==pracownik.id).select()
			if user: user=user[0]
			else : return "system error - brak uzytkownika"
			password = self.random_password() 
			if self.settings.mailer.send(to=request.vars.email, 
						subject=self.messages.retrieve_password_subject, 
						message=self.messages.retrieve_password % dict(password=password)):
				user.update_record(password=utils.md5_hash(password))
				redirect(URL(a='instytut', c='home', f='komunikat', vars={'message': 'wysłano maila z nowym hasłem na adres: ' + request.vars.email})) 
			else:
				redirect(URL(a='instytut', c='home', f='komunikat', vars={'message': 'niepowiodło się wysłanie maila na adres: ' + request.vars.email})) 
		return form
	
	def odswierz(self,form):
		if auth.user:
			pass
			#auth.user.first_name=form.vars.first_name
			#auth.user.last_name=form.vars.last_name
			#auth.user.email=form.vars.email
	
	def login( 
		self, 
		next=DEFAULT, 
		onvalidation=DEFAULT, 
		onaccept=DEFAULT, 
		log=DEFAULT, 
		): 
		""" 
		returns a login form 
		""" 
		table_user = self.settings.table_user 
		if 'username' in table_user.fields: 
			username = 'username' 
		else: 
			username = 'email' 
		#old_requires = table_user[username].requires 
		#table_user[username].requires = IS_NOT_EMPTY() 
		request = self.environment.request 
		response = self.environment.response 
		session = self.environment.session 
		if not request.vars._next: 
			request.vars._next = request.env.http_referer or '' 
		if next == DEFAULT: 
			next = request.vars._next or self.settings.login_next 
		if onvalidation == DEFAULT: 
			onvalidation = self.settings.login_onvalidation 
		if onaccept == DEFAULT: 
			onaccept = self.settings.login_onaccept 
		if log == DEFAULT: 
			log = self.messages.login_log 
		password = self.settings.password_field
		

		form = FORM(TABLE(TR("email: ", INPUT(_type='text', _name="email", 
		     requires=[IS_EMAIL(), IS_IN_DB(db, 'pracownicy.email', error_message="podany email nie istnieje")])),
		                 TR("hasło: ", INPUT(_type='password', _name='password', 
								   requires=db.uzytkownicy.password.requires)),
								TR("", INPUT(_type='submit', _value='Wyślij')),
								))
		if form.accepts(request.vars, session): 
			#znajdz pracownika i wez jego id, na pewno jest - validacja przez request w formularzu
			pracownik = db(db.pracownicy.email==form.vars.email).select(db.pracownicy.id, db.pracownicy.imie)[0]

			#znajdz uzytkownika wskazującego na takiego użytkownika
			user = db(db.uzytkownicy.id_pracownik==pracownik.id).select()
			if user: user=user[0]
			else : return "system error"
			
			if user.registration_key == 'pending': 
				response.flash = self.messages.registration_pending 
				return form 
			elif user.registration_key == 'disabled': 
				response.flash = self.messages.login_disabled 
				return form 
			elif user.registration_key: 
				response.flash = self.messages.registration_verifying 
				return form 

			#sprawdzenie hasła
			if user[password] != form.vars.get(password,''): 
				response.flash = "błędna para użytkownik - hasło"
				return form
				 
			user = Storage(table_user._filter_fields(user, id=True), imie=pracownik.imie) 
			session.auth = Storage(user=user, last_visit=request.now, 
								   expiration=self.settings.expiration) 
			self.user = user 
			session.flash = self.messages.logged_in 
			if log and self.user: 
				self.log_event(log % self.user) 
			if onaccept: 
				onaccept(form) 
			if not next: 
				next = self.url() 
			elif next and not next[0] == '/' and next[:4] != 'http': 
				next = self.url(next.replace('[id]', str(form.vars.id))) 
			redirect(URL(a='instytut', c='home', f='komunikat', vars={'message': 'zalogowano'})) 

		return form 

	def change_password(
        self,
        next=DEFAULT,
        onvalidation=DEFAULT,
        onaccept=DEFAULT,
        log=DEFAULT,
        ):

		if not self.is_logged_in():
			redirect(self.settings.login_url)

		request = self.environment.request
		pass1 = request.vars.password1
		if not request.vars._next:
			request.vars._next = request.env.http_referer or ''
		
		cry = CRYPT()
		#print 'u:', (self.user.password)
		#if request.vars.password:
		#	print 'p:', cry(request.vars.password)[0]
		form = FORM(TABLE(TR('Stare hasło: ', INPUT(_type='password', _name='password',
									 requires=[db.uzytkownicy.password.requires, IS_EXPR('value==%s' % repr(self.user.password), error_message='niepoprawne hasło')])),
		                 TR("Nowe hasło: ", INPUT(_type='password', _name='password1', 
									 requires=db.uzytkownicy.password.requires)),
		                 TR("Powtórz hasło: ", INPUT(_type='password', _name='password2', 
									 requires=[IS_EXPR('value==%s' % repr(pass1), error_message='hasła się nie zgadzają')])),
							  TR("", INPUT(_type='submit', _value='Zatwierdź')),
							))
									 
		if form.accepts(request.vars, session):
				auth.user.password=form.vars.new_password
				session.flash = self.messages.password_changed
				log = self.settings.change_password_log
				if log:
					 self.log_event(log % self.user)
				self.db.uzytkownicy[self.user.id]=dict(password=cry(pass1)[0])
				self.db.commit()
				redirect(URL(a='instytut', c='home', f='komunikat', vars={'message': 'zmieniono hasło'})) 

		return form
	
	

	def __call__(self):
		def kon(url):
			return url.split('/')[-1]
		request = self.environment.request 
		args = request.args
		if not args: 
			redirect(self.url(args='login')) 
		if args[0] == kon(self.settings.login_url): 
			return self.login() 
		elif args[0] == kon(self.settings.logout_url): 
			return self.logout() 
		elif args[0] == kon(self.settings.register_url): 
			return self.register() 
		elif args[0] == kon(self.settings.retrieve_password_url): 
			return self.retrieve_password() 
		elif args[0] == kon(self.settings.change_password_url):
			return self.change_password() 
		elif args[0] == kon(self.settings.profile_url):
			return self.profile() 
		else: 
			raise HTTP(404) 
	
	def profile( 
		self, 
		next=DEFAULT, 
		onvalidation=DEFAULT, 
		onaccept=DEFAULT, 
		log=DEFAULT, 
		readonly_fields=['id_rola','id_pracownik'],
		readonly=1
		): 
		#returns a form that lets the user change his/her profile 
		if not self.is_logged_in(): 
			redirect(self.settings.login_url) 
		password = self.settings.password_field 
		self.settings.table_user[password].writable = False 
		request = self.environment.request 
		session = self.environment.session 
		if not request.vars._next: 
			request.vars._next = request.env.http_referer or '' 
		if next == DEFAULT: 
			next = self.settings.profile_next or request.vars._next 
		if onvalidation == DEFAULT: 
			onvalidation = self.settings.profile_onvalidation 
		if onaccept == DEFAULT: 
			onaccept = self.settings.profile_onaccept 
		if log == DEFAULT: 
			log = self.settings.profile_log 
		form = ProfessorsSQLFORM( 
			self.settings.table_user, 
			self.user.id, 
			hidden=dict(_next=request.vars._next), 
			showid=self.settings.showid, 
			submit_button=self.settings.submit_button,
			delete_label=self.settings.delete_label, 
			readonly_fields=readonly_fields,
			readonly=readonly
			)
		if form.accepts(request.vars, session, 
				  formname='profile', 
				  onvalidation=onvalidation): 
			session.flash = self.messages.profile_updated 
			log = self.settings.profile_log 
			if log: 
				self.log_event(log % self.user) 
			if onaccept: 
				onaccept(form) 
			if not next: 
				next = URL(r=request) 
			elif next and not next[0] == '/' and next[:4] != 'http': 
				next = URL(r=request, f=next.replace('[id]', 
					str(form.vars.id))) 
			redirect(next) 
		return form 
		
	def has_membership(self, group_id): 
		""" 
		sprawdza czy aktualny uzytkownik nalezy do grupy group_id
		""" 
		r = self.user and self.user.id_rola==group_id
		log = self.settings.has_membership_log 
		if log: 
			self.log_event(log % dict(group_id=group_id, check=r)) 
		return r 
	
	def has_any_membership(self, group_ids): 
		""" 
		sprawdza czy aktualny uzytkownik nalezy do którejś z group_ids
		"""
		for group_id in group_ids:
			if self.has_membership(group_id):
				return 1
		return 0
	
	def requires_any_membership(self, group_ids): 
		"""
		sprawdza czy należy do której z podanych grup (group_ids = [id_grup])
		"""
		def decorator(action): 
			def f(*a, **b): 
				if not self.is_logged_in(): 
					redirect(self.settings.login_url) 
				if not any(map(lambda group_id : self.has_membership(group_id),group_ids)):
					self.environment.session.flash = self.messages.access_denied 
					next = redirect(URL(a='instytut',c='home',f='komunikat', vars={'message': "Nie posiadasz uprawnien"}))
				return action(*a, **b) 
			return f 
		return decorator
		
	def id_group(self, role): 
		rows = self.db(self.settings.table_group.nazwa == role).select() 
		if not rows: 
			return None 
		return rows[0].id 
	
	"""
	def tworz_grupy(self):
		if 'grupy' in db: db.grupy.truncate()
		self.grupa_administrator = self.add_group(role = "Administrator", description ='')
		self.grupa_moderator_instytutowy = self.add_group(role = "Moderator instytutowy", 
				description = '')
		self.grupa_pracownik = self.add_group(role = "Pracownik", description = '')
	"""
	

auth=ProfessorsAuth(globals(), db)
auth.define_tables()

#lista wszystkich nazw tabel w bazie
db_tables=['tyt_nauk','form_zatr','instytut','dyscyplina','czas_pracy','zaklad', 'pracownicy','uzytkownicy','grupy','rola','rodzaj_czasopisma','czasopisma','publikacje','publikacje_pracownicy', 'rodzaje_grantow', 'granty', 'granty_pracownicy']

crud=ProfessorsCrud(globals(),db)
